package org.interactive.spring.intro.service;

import com.sun.tools.internal.ws.wsdl.framework.ValidationException;
import org.interactive.spring.intro.component.UserProcessingComponent;
import org.interactive.spring.intro.dao.UsersDAO;
import org.interactive.spring.intro.entities.Address;
import org.interactive.spring.intro.entities.Company;
import org.interactive.spring.intro.entities.User;
import org.interactive.spring.intro.exceptions.UserNotFoundException;
import org.interactive.spring.intro.transport.AddressTO;
import org.interactive.spring.intro.transport.UserTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * UsersServiceImpl class
 *
 * @author bogdan.solga
 *
 * Date: 05.06.2013, time: 09:44
 */
@Service
@Transactional(readOnly = true)
public class UsersServiceImpl implements UsersService {

    private static final Logger log = LoggerFactory.getLogger(UsersServiceImpl.class);

    @Autowired
    private UsersDAO usersDAO;

    @Autowired
    private UserProcessingComponent userProcessingComponent;

    public UserTO getByUserName(String userName) throws UserNotFoundException {
        User user = usersDAO.getByUserName(userName);
        if (user == null) {
            log.warn("There is no user with the username '{}'", userName);
            throw new UserNotFoundException("There is no user with the username '" + userName + "'");
        }

        userProcessingComponent.processUser(user);

        return buildUserTO(user);
    }

    public List<UserTO> getAllUsers(String name) {
        List<User> users = usersDAO.getAll(name);
        if (users == null || users.size() == 0) {
            log.warn("There are no users with the first name '{}'", name);
            return null;
        }

        List<UserTO> userTOs = new LinkedList<UserTO>();
        for (User user : users) {
            userTOs.add(buildUserTO(user));
        }

        return userTOs;
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void save(UserTO user) throws ValidationException {
        User entity = new User();

        entity.setUserId(new Random().nextInt());

        Company company = new Company();
        company.setCompanyId(23);
        company.setCompanyName("3PG");

        entity.setCompany(company);

        entity.setUserName(user.getUserName());
        entity.setFirstName(user.getFirstName());
        entity.setLastName(user.getLastName());

        usersDAO.save(entity);
    }

    private static UserTO buildUserTO(User user) {
        UserTO userTO = new UserTO();

        userTO.setUserName(user.getUserName());
        userTO.setFirstName(user.getFirstName());
        userTO.setLastName(user.getLastName());

        Set<Address> addresses = user.getAddresses();
        if (addresses != null && addresses.size() > 0) {
            Set<AddressTO> addressTOs = new HashSet<AddressTO>();
            for (Address address : addresses) {
                addressTOs.add(buildAddressTO(address));
            }

            userTO.setAddresses(addressTOs);
        }

        return userTO;
    }

    private static AddressTO buildAddressTO(Address address) {
        AddressTO addressTO = new AddressTO();

        addressTO.setHouseNumber(address.getHouseNumber());
        addressTO.setStreet(address.getStreet());

        return addressTO;
    }
}
